//* global window */
import { h } from './element'
import Suggest from './suggest'
import Datepicker from './datepicker'
import { cssPrefix } from '../config'
// import { mouseMoveUp } from '../event';

function resetTextareaSize() {
  const { inputText } = this
  if (!/^\s*$/.test(inputText)) {
    const { textlineEl, textEl, areaOffset } = this
    const txts = inputText.split('\n')
    const maxTxtSize = Math.max(...txts.map((it) => it.length))
    const tlOffset = textlineEl.offset()
    const fontWidth = tlOffset.width / inputText.length
    const tlineWidth = (maxTxtSize + 1) * fontWidth + 5
    const maxWidth = this.viewFn().width - areaOffset.left - fontWidth
    let h1 = txts.length
    if (tlineWidth > areaOffset.width) {
      let twidth = tlineWidth
      if (tlineWidth > maxWidth) {
        twidth = maxWidth
        h1 += parseInt(tlineWidth / maxWidth, 10)
        h1 += tlineWidth % maxWidth > 0 ? 1 : 0
      }
      textEl.css('width', `${twidth}px`)
    }
    h1 *= this.rowHeight
    if (h1 > areaOffset.height) {
      textEl.css('height', `${h1}px`)
    }
  }
}

function insertText({ target }, itxt) {
  const { value, selectionEnd } = target
  const ntxt = `${value.slice(0, selectionEnd)}${itxt}${value.slice(
    selectionEnd
  )}`
  target.value = ntxt
  target.setSelectionRange(selectionEnd + 1, selectionEnd + 1)

  this.inputText = ntxt
  this.textlineEl.html(ntxt)
  resetTextareaSize.call(this)
}

function keydownEventHandler(evt) {
  const { keyCode, altKey } = evt
  if (keyCode !== 13 && keyCode !== 9) evt.stopPropagation()
  if (keyCode === 13 && altKey) {
    insertText.call(this, evt, '\n')
    evt.stopPropagation()
  }
  if (keyCode === 13 && !altKey) evt.preventDefault()
}

function inputEventHandler(evt) {
  const v = evt.target.value
  // console.log(evt, 'v:', v);
  const { suggest, textlineEl, validator } = this
  const { cell } = this
  if (cell !== null) {
    if (
      ('editable' in cell && cell.editable === true) ||
      cell.editable === undefined
    ) {
      this.inputText = v
      if (validator) {
        if (validator.type === 'list') {
          suggest.search(v)
        } else {
          suggest.hide()
        }
      } else {
        const start = v.lastIndexOf('=')
        if (start !== -1) {
          suggest.search(v.substring(start + 1))
        } else {
          suggest.hide()
        }
      }
      textlineEl.html(v)
      resetTextareaSize.call(this)
      this.change('input', v)
    } else {
      evt.target.value = ''
    }
  } else {
    this.inputText = v
    if (validator) {
      if (validator.type === 'list') {
        suggest.search(v)
      } else {
        suggest.hide()
      }
    } else {
      const start = v.lastIndexOf('=')
      if (start !== -1) {
        suggest.search(v.substring(start + 1))
      } else {
        suggest.hide()
      }
    }
    textlineEl.html(v)
    resetTextareaSize.call(this)
    this.change('input', v)
  }
}

function setTextareaRange(position) {
  const { el } = this.textEl
  setTimeout(() => {
    el.focus()
    el.setSelectionRange(position, position)
  }, 0)
}

function setText(text, position) {
  const { textEl, textlineEl } = this
  // firefox bug
  textEl.el.blur()

  textEl.val(text)
  textlineEl.html(text)
  setTextareaRange.call(this, position)
}

function suggestItemClick(it) {
  const { inputText, validator } = this
  let position = 0
  if (validator && validator.type === 'list') {
    this.inputText = it
    position = this.inputText.length
  } else {
    const start = inputText.lastIndexOf('=')
    const sit = inputText.substring(0, start + 1)
    let eit = inputText.substring(start + 1)
    if (eit.indexOf(')') !== -1) {
      eit = eit.substring(eit.indexOf(')'))
    } else {
      eit = ''
    }
    this.inputText = `${sit + it.key}(`
    // console.log('inputText:', this.inputText);
    position = this.inputText.length
    this.inputText += `)${eit}`
  }
  setText.call(this, this.inputText, position)
}

function resetSuggestItems() {
  this.suggest.setItems(this.formulas)
}

function dateFormat(d) {
  let month = d.getMonth() + 1
  let date = d.getDate()
  if (month < 10) month = `0${month}`
  if (date < 10) date = `0${date}`
  return `${d.getFullYear()}-${month}-${date}`
}

export default class Editor {
  constructor(formulas, viewFn, rowHeight) {
    this.viewFn = viewFn
    this.rowHeight = rowHeight
    this.formulas = formulas
    this.suggest = new Suggest(formulas, (it) => {
      suggestItemClick.call(this, it)
    })
    this.datepicker = new Datepicker()
    this.datepicker.change((d) => {
      // console.log('d:', d);
      this.setText(dateFormat(d))
      this.clear()
    })
    this.areaEl = h('div', `${cssPrefix}-editor-area`)
      .children(
        (this.textEl = h('textarea', '')
          .on('input', (evt) => inputEventHandler.call(this, evt))
          .on('paste.stop', () => {})
          .on('keydown', (evt) => keydownEventHandler.call(this, evt))),
        (this.textlineEl = h('div', 'textline')),
        this.suggest.el,
        this.datepicker.el
      )
      .on('mousemove.stop', () => {})
      .on('mousedown.stop', () => {})
    this.el = h('div', `${cssPrefix}-editor`)
      .child(this.areaEl)
      .hide()
    this.suggest.bindInputEvents(this.textEl)

    this.areaOffset = null
    this.freeze = { w: 0, h: 0 }
    this.cell = null
    this.inputText = ''
    this.change = () => {}
  }

  setFreezeLengths(width, height) {
    this.freeze.w = width
    this.freeze.h = height
  }

  clear() {
    // const { cell } = this;
    // const cellText = (cell && cell.text) || '';
    if (this.inputText !== '') {
      this.change('finished', this.inputText)
    }
    this.cell = null
    this.areaOffset = null
    this.inputText = ''
    this.el.hide()
    this.textEl.val('')
    this.textlineEl.html('')
    resetSuggestItems.call(this)
    this.datepicker.hide()
  }

  setOffset(offset, suggestPosition = 'top') {
    const { textEl, areaEl, suggest, freeze, el } = this
    if (offset) {
      this.areaOffset = offset
      const { left, top, width, height, l, t } = offset
      // console.log('left:', left, ',top:', top, ', freeze:', freeze);
      const elOffset = { left: 0, top: 0 }
      // top left
      if (freeze.w > l && freeze.h > t) {
        //
      } else if (freeze.w < l && freeze.h < t) {
        elOffset.left = freeze.w
        elOffset.top = freeze.h
      } else if (freeze.w > l) {
        elOffset.top = freeze.h
      } else if (freeze.h > t) {
        elOffset.left = freeze.w
      }
      el.offset(elOffset)
      areaEl.offset({
        left: left - elOffset.left - 0.8,
        top: top - elOffset.top - 0.8,
      })
      textEl.offset({ width: width - 9 + 0.8, height: height - 3 + 0.8 })
      const sOffset = { left: 0 }
      sOffset[suggestPosition] = height
      suggest.setOffset(sOffset)
      suggest.hide()
    }
  }

  setCell(cell, validator) {
    // console.log('::', validator);
    const { el, datepicker, suggest } = this
    el.show()
    this.cell = cell
    const text = (cell && cell.text) || ''
    this.setText(text)

    this.validator = validator
    if (validator) {
      const { type } = validator
      if (type === 'date') {
        datepicker.show()
        if (!/^\s*$/.test(text)) {
          datepicker.setValue(text)
        }
      }
      if (type === 'list') {
        suggest.setItems(validator.values())
        suggest.search('')
      }
    }
  }

  setText(text) {
    this.inputText = text
    // console.log('text>>:', text);
    setText.call(this, text, text.length)
    resetTextareaSize.call(this)
  }
}
